from os import popen,system
import time
import subprocess
import re
#### Add user define split func -> userSplit 2010.4.14 ####
class ReadStatic:
	def __init__(self,confdir,tmpdir,outdir, cNum=11):
		self.__cNumber = cNum
		self.__confdir = confdir
		self.__outFile = []
		self.__tmpdir = tmpdir
		self.__toWrite = {}
		self.__svrList = {}
		self.__ip2id = {}
		self.__comRe = []
		self.__codeIn = ['200','304']
		self.__outdir = outdir
		self.__JudgeIn = []
		self.__JudgeStart = []
		self.__IPreg = re.compile('\s*inet ([^ ]+)')
		self.__myIP =''
		self.__JudgeEq = []
		self.__whitesign = []
		self.__auto = {'dir':self.__JudgeIn.extend,'start':self.__JudgeStart.extend,'req':self.__JudgeEq.extend,'white':self.__whitesign.extend}
		self.__basic = self.readConf('basic')

	def AddCode(self,nCode):
		''' Can add All code in '''
		self.__codeIn.extend(nCode)

	def HostTab(self):
		f = open('%s/host.conf' % self.__confdir)
		for line in f:
			svrIP,svrID = line.strip().split('\t')
			self.__svrList[svrID] = svrIP
			self.__ip2id[svrIP] = svrID
		f.close()

	def GetIP(self):
		mycmd = '/sbin/ifconfig -a'
		rsyncDaemon = subprocess.Popen(mycmd, shell=True,close_fds=True,stdout=subprocess.PIPE, stderr=subprocess.PIPE)
		conTMP = rsyncDaemon.communicate()
		self.__myIP = filter(lambda x: x in self.__svrList.values(), self.__IPreg.findall(conTMP[0]))[0]
		return self.__myIP

	def AddWhiteList(self,cont):
		self.__whitesign.extend(cont)

	def openFile(self,logname,logdir=''):
		if len(logdir) < 1: logdir=self.__outdir

		for i in range(self.__cNumber):
			#print '%s/%s.%s' % (logdir,logname,i)
			self.__toWrite[i] = open('%s/%s.%s' % (logdir,logname,i),'w')
			self.__outFile.append('%s.%s' % (logname,i))
	
	def writeFile(self,logsign,content):
		logsign = int(logsign)
		self.__toWrite[logsign].write(content)

	def closeFile(self):
		for fKey in self.__toWrite:
			self.__toWrite[fKey].close()

	def transSec(self,secPattern):
		self.__SecHash = secPattern

	def readConf(self,channel):
		if channel == 'basic':
			f = open('%s/Exclude/baseEx.conf' % self.__confdir)
		else:
			f = open('%s/Exclude/%s_Ex.conf' % (self.__confdir,channel))

		for line in f:
			Jtmp = []
			(Jtype,Jcont) = line.strip().split('\t')
			Jtmp = Jcont.split(',')
			self.__auto[Jtype](Jtmp)
		f.close()

	def readConf_o(self,channel):
		if channel == 'basic':
			f = open('%s/Exclude/baseEx.conf' % self.__confdir)
		else:
			f = open('%s/Exclude/%s_Ex.conf' % (self.__confdir,channel))

		for line in f:
			Jtmp = []
			(Jtype,Jcont) = line.strip().split('\t')
			Jtmp = Jcont.split(',')
			self.__comRe.extend(Jtmp)
		f.close()

	#def combinedRe(self):
		#self.__filters = re.compile(r"%s" % ('|'.join(self.__comRe)),re.I)


	def readLog(self,logdir,logfile,secCH=False,whiteSign=False):
		if logfile.endswith('.gz'):
			f = popen('gunzip -c %s/%s' % (logdir,logfile))
		else:
			f = open('%s/%s' % (logdir,logfile))

		for line in f:
			hostname = ''
			lineTMP = line.split()
			DangerIndex2,DangerIndex1 = 0,0

			if not ('"GET' in lineTMP or '"POST' in lineTMP) or lineTMP[0] == '-': continue
			#### For new LogFMT ###
			#### First segment is a hostname, so it shouldn't all be digit. ####

			if filter(lambda x: not x.isdigit(), lineTMP[0].split('.')):
				if not ',' in lineTMP[0]: hostname = lineTMP[0]
				lineTMP.remove(lineTMP[0])

			################## Justfy Log Format ##############

			if ',' in lineTMP[0]:
				lineTMP[0]= lineTMP[0][:-1]
				#nextIndex = lineTMP.index('-')
				while not lineTMP[3].startswith('['):
					#nextIndex -= 1
					lineTMP.remove(lineTMP[1])

			try:
				DangerIndex1 = lineTMP.index('+0800]')
			except:
				#######################
				#print lineTMP
				continue
				raise "TimeArea Error."


			try:
				i2 = 0
				DangerIndex2 = lineTMP.index('"GET')
			except:
				i2 = 1
			if DangerIndex2 < 1 :
				try:
					i3 = 0
					DangerIndex2 = lineTMP.index('"POST')
				except:
					if i2 < 1:
						raise "HTTP Method Error."

			Distance12 = DangerIndex2 - DangerIndex1

			while Distance12 != 1:
				#lineTMP.remove(lineTMP[DangerIndex2-1])
				lineTMP.remove(lineTMP[Distance12-1])
				Distance12 -= 1

			####################################################
			if len(lineTMP) < 8: continue
			if len(lineTMP) < 12: continue
			if hostname: lineTMP[11] = hostname
			if lineTMP[8].isdigit() and lineTMP[8] in self.__codeIn:
				if secCH:
					if self.secFilter(lineTMP[6]):
						continue
				if whiteSign:
					if self.filterWhite(lineTMP[6]):
						yield lineTMP[6],' '.join(lineTMP)
						continue
					else:
						continue
				else:
					if self.filterAct(lineTMP[6]):
						#yield lineTMP[0],lineTMP[6],lineTMP[10]
						#yield lineTMP[6],' '.join(lineTMP)
						yield lineTMP[6],lineTMP
					else:
						continue
			else:
				continue
		f.close()


	def filterWhite(self,line):
		if '?' in line: line=line[:line.index('?')]
		for tmp in self.__whitesign:
			if line.startswith(tmp): return True
		return False
	
	def filterAct_o(self,line):
		try:
			if self.__filters.search(line[:line.index('?')]): return False
		except:
			if self.__filters.search(line): return False
		return True

	def filterAct(self,line):
		if '?' in line: line=line[:line.index('?')]

		if '.' in line:
			lineType = line[line.rindex('.'):]
			if lineType in self.__JudgeEq: return False

		for tmp in self.__JudgeIn:
			if tmp in line:
				return False

		if line in self.__JudgeEq: return False
		for tmp in self.__JudgeStart:
			if line.startswith('%s' % tmp): return False

		return True

	def secFilter(self,req):
		for f_req in self.__SecHash:
			if req.startswith(f_req):
				return False

		return True
	
	def splitFile(self,uid):
		try:
			startPOS = uid.rindex('_')+1
		except:
			#print "ok"
			return False
		
		try:
			id_num = int(uid[startPOS:])%self.__cNumber

		except:
			#raise "%s id error" % uid
			return False
		return str(id_num)
	
	def userSplit(self,uid):
		''' pleast give me INT. '''
		#if type(uid) != int: return False
		if not str(uid).isdigit(): return False
		
		try:
			id_num = int(uid)%self.__cNumber

		except:
			#raise "%s id error" % uid
			return False
		return str(id_num)

	def ChangeFile(self):
		self.HostTab()
		myIP = self.GetIP()
		reTry,rsyncDaemon = 0,('','')
		for fileName in self.__outFile:
			svrKey = fileName[fileName.rindex('.')+1:]
			if self.__svrList[svrKey] == myIP: continue
			mycmd = 'rsync %s/%s %s::Grid_tract/' % (self.__outdir,fileName,self.__svrList[svrKey])

			for reTry in range(5):
				rsyncDaemon = subprocess.Popen(mycmd, shell=True,close_fds=True,stdout=subprocess.PIPE, stderr=subprocess.PIPE)
				RsyncDetail = rsyncDaemon.communicate()
				rsyncCode = rsyncDaemon.returncode
				if  rsyncCode != 0:
					print 'die %s %s' % (self.__svrList[svrKey],RsyncDetail[1])
					if 'No such file or directory' in RsyncDetail[1]: break
					time.sleep(15)
					continue
					#return False
				break
			system('rm -f %s/%s' % (self.__outdir,fileName))
		del self.__outFile
		self.__outFile = []
		return True

	def shortSort(self,filename,sortKey,fHandle):
		#sTMP is an array that contain the position of values which to be compared
		sTMP = []
		#f = open('%s/%s' % (self.__tmpdir,filename))
		f = open('%s' % filename)
		for line in f:
			sTMP.append(tuple(line.split('\t')))
		for line1 in sorted(sTMP,key=lambda y: map(lambda x:y[int(x)],sortKey)):
			fHandle.write("\t".join(line1))
			#fHandle.write("\n")
		f.close()

#	def ArgSplit(self, argstr, m_sep='&', sm_sep='='):
#		return map(lambda x: map(lambda x: x or '-', x.split(sm_sep,1)), argstr.split(m_sep))
		
	def ArgSplit(self, argstr, m_sep='&', sm_sep='='):
		i = 0
		tmpElement = []
		tmplist = map(lambda x: map(lambda x: x or '-', x.split(sm_sep,1)), argstr.split(m_sep))
		#print tmplist
		for tmpEnum in range(len(tmplist)):
			if len(tmplist[tmpEnum]) < 2:
				if tmpEnum < 1: return False
				tmpElement.append(tmpEnum)
		
				
		for x in tmpElement:
			del tmplist[x-i]
			i += 1
		return tmplist 

			
			



























